package com.ciei.dpagm.service;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ciei.dpagm.entity.*;
import com.ciei.dpagm.common.enums.ErrorCodeEnum;
import com.ciei.dpagm.common.enums.RoleEnableEnum;
import com.ciei.dpagm.common.enums.RoleIsSystemEnum;
import com.ciei.dpagm.common.service.BaseService;
import com.ciei.dpagm.mapper.RoleMapper;
import com.ciei.dpagm.util.APP;
import com.ciei.dpagm.util.JsonUtil;
import com.ciei.dpagm.util.PageParam;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.function.BiFunction;
import java.util.stream.Collectors;

@Service
public class RoleService extends BaseService<RoleMapper, Role> {

    @Autowired
    RoleRightService roleRightService;
    @Autowired
    private UserRoleService userRoleService;
    @Autowired
    private UsersService usersService;
    @Autowired
    private DepartmentService departmentService;

    /**
     * 新增或修改角色
     * @param roleJson 角色数据
     * @return
     */
    public JSONObject saveOrUpdate(JSONObject roleJson) {
        Role role = JSON.parseObject(roleJson.toJSONString(), Role.class);
        if (role == null) {
            return JsonUtil.getFail(ErrorCodeEnum.INVALID_PARAM, "无效参数");
        }
        if (StringUtils.isBlank(role.getRoleName())) {
            return JsonUtil.getFail(ErrorCodeEnum.INVALID_PARAM, "角色名称不能为空");
        }
        if (role.getEnable() == null) {
            return JsonUtil.getFail(ErrorCodeEnum.INVALID_PARAM, "enable字段不能为空");
        }
        Integer roleId = role.getRoleId();
        // 新增时，默认为普通角色
        if (roleId == null) {
            role.setIsSystem(RoleIsSystemEnum.COMMON_ROLE.getValue());
        }

        // 检查 roleCode 是否唯一
        boolean roleCodeIsUnique;
        String roleCode = role.getRoleCode();
        if (StringUtils.isNotBlank(roleCode)) {
            if (roleId == null) {
                roleCodeIsUnique = roleCodeIsUnique(roleCode, null);
            } else {
                roleCodeIsUnique = roleCodeIsUnique(roleCode, roleId);
            }
            if (!roleCodeIsUnique) {
                return JsonUtil.getFail(ErrorCodeEnum.INVALID_PARAM, "角色编码已存在");
            }
        }

        boolean success = saveOrUpdate(role);
        if (success) {
            return JsonUtil.getSuccess("操作成功").fluentPut(APP.DATA, role);
        } else {
            return JsonUtil.getFail(ErrorCodeEnum.DATA_OPERATION_FAIL, "操作失败").fluentPut(APP.DATA, role);
        }

    }

    /**
     * 检查roleCode是否唯一
     * @param checkRoleCode 要检查的roleCode
     * @param exceptRoleId 排除roleId,一般是本身
     * @return true 表示参数“checkRoleCode”是唯一的
     */
    public boolean roleCodeIsUnique(String checkRoleCode, Integer exceptRoleId) {
        if (StringUtils.isBlank(checkRoleCode)) {
            return false;
        }
        LambdaQueryWrapper<Role> wrapper = Wrappers.lambdaQuery();
        wrapper.eq(Role::getRoleCode, checkRoleCode);
        if (exceptRoleId != null) {
            wrapper.ne(Role::getRoleId, exceptRoleId);
        }
        return count(wrapper) == 0;
    }

    /**
     * 批量分配权限
     * @param configJson 配置数据
     * @return
     */
    public JSONObject setRoleRights(JSONObject configJson) {
        Integer roleId = configJson.getInteger("roleId");
        if (roleId == null) {
            return JsonUtil.getFail(ErrorCodeEnum.INVALID_PARAM, "roleId不能为空");
        }
        boolean success;
        JSONArray rightIdArray = configJson.getJSONArray("rightIds");
        if (rightIdArray == null || rightIdArray.isEmpty()) {
            success = roleRightService.saveOrUpdate(roleId, null);
        } else {
            success = roleRightService.saveOrUpdate(roleId, rightIdArray.toJavaList(Integer.class));
        }
        if (success) {
            return JsonUtil.getSuccess("配置成功");
        } else {
            return JsonUtil.getFail(ErrorCodeEnum.DATA_OPERATION_FAIL, "配置失败");
        }
    }

    /**
     * 角色批量添加用户
     * @param configJson 配置数据
     * @return
     */
    public JSONObject addRoleUsers(JSONObject configJson) {
        return saveOrDeleteRoleUsers(configJson, (roleId, userIds) -> userRoleService.save(roleId, userIds));
    }

    /**
     * 角色批量移除用户
     * @param configJson 配置数据
     * @return
     */
    public JSONObject removeRoleUsers(JSONObject configJson) {
        return saveOrDeleteRoleUsers(configJson, (roleId, userIds) -> userRoleService.delete(roleId, userIds));
    }

    /**
     * 管理用户
     * @param configJson  配置数据
     * @param saveOrDeleteFunction 添加或删除用户的操作函数
     * @return
     */
    public JSONObject saveOrDeleteRoleUsers(JSONObject configJson,BiFunction<Integer,Collection<Integer>,Boolean> saveOrDeleteFunction) {
        Integer roleId = configJson.getInteger("roleId");
        if (roleId == null) {
            return JsonUtil.getFail(ErrorCodeEnum.INVALID_PARAM, "roleId不能为空");
        }
        JSONArray userIdArray = configJson.getJSONArray("userIds");
        if (userIdArray == null || userIdArray.isEmpty()) {
            return JsonUtil.getFail(ErrorCodeEnum.INVALID_PARAM, "userIds不能为空");
        }
        boolean success = saveOrDeleteFunction.apply(roleId,userIdArray.toJavaList(Integer.class));
        if (success) {
            return JsonUtil.getSuccess("操作成功");
        } else {
            return JsonUtil.getFail(ErrorCodeEnum.DATA_OPERATION_FAIL, "操作失败");
        }
    }

    /**
     * 加载角色拥有的用户
     *
     * @param ps 分页请求参数
     * @return 用户表格数据
     */
    public JSONObject loadUserGridInRole(PageParam ps) {
        return loadUserGrid(ps, this::getUserPageInRole);
    }

    /**
     * 加载不属于该角色的用户
     *
     * @param ps 分页请求参数
     * @return 用户表格数据
     */
    public JSONObject loadUserGridOutRole(PageParam ps) {
        return loadUserGrid(ps, this::getUserPageOutRole);
    }

    /**
     * 构造查询条件：加载角色拥有的用户
     *
     * @param ps        请求参数
     * @param userIdSet 角色拥有的用户ID
     * @return 条件包装器
     */
    public IPage<Users> getUserPageInRole(PageParam ps, Set<Integer> userIdSet) {
        Map<String, Object> params = ps.getParams();
        Map<String, Object> sortFields = ps.getSort();
        int currentPage = ps.getCurrentPage();
        int pageSize = ps.getPageSize();
        String[] likeFields = {"loginName", "userName", "jobCode"};
        String[] inFields = {"userId"};
        if (userIdSet == null || userIdSet.isEmpty()) {
            IPage<Users> page = new Page<>();
            page.setSize(pageSize);
            page.setCurrent(currentPage);
            return page;
        } else {
            params.put("userId", new ArrayList<>(userIdSet));
            QueryWrapper<Users> queryWrapper = usersService.getFormSearchWrapperLikeAnd(params, likeFields, null, sortFields, inFields);
            return usersService.findPageVue(currentPage, pageSize, queryWrapper);
        }
    }

    /**
     * 构造查询条件：加载不属于该角色的用户
     *
     * @param ps        请求参数
     * @param userIdSet 角色拥有的用户ID
     * @return 条件包装器
     */
    public IPage<Users> getUserPageOutRole(PageParam ps, Set<Integer> userIdSet) {
        Map<String, Object> params = ps.getParams();
        Map<String, Object> sortFields = ps.getSort();
        int currentPage = ps.getCurrentPage();
        int pageSize = ps.getPageSize();
        String[] likeFields = {"loginName", "userName", "jobCode"};
        String[] inFields = {"departmentId"};

        //根据当前的公司和部门数据查询对应的用户数据，如果是父部门，对应子部门的用户数据也要查询
        if (params.containsKey("departmentId")) {
            Integer departmentId = (Integer) params.get("departmentId");
            if (departmentId != null) {
                Set<Integer> childrenIds = new HashSet<>();
                List<Department> allDepartment = departmentService.getBaseMapper().listSameCompanyDepartments(departmentId);
                departmentService.loadChildrenDepartmentIds(allDepartment, departmentId, childrenIds);
                params.put("departmentId", new ArrayList<>(childrenIds));
            }
        }
        QueryWrapper<Users> queryWrapper = usersService.getFormSearchWrapperLikeAnd(params, likeFields, null, sortFields, inFields);
        if (userIdSet != null && !userIdSet.isEmpty()) {
            queryWrapper.lambda().notIn(Users::getUserId, userIdSet);
        }
        return usersService.findPageVue(currentPage, pageSize, queryWrapper);
    }

    /**
     * 根据条件查询用户列表
     * @param ps 请求参数
     * @param getUserPage 获取分页的函数
     * @return 用户表格信息
     */
    public JSONObject loadUserGrid(PageParam ps, BiFunction<PageParam, Set<Integer>, IPage<Users>> getUserPage) {
        Map<String, Object> params = ps.getParams();
        Map<String, Object> sortFields = ps.getSort();
        if (sortFields.isEmpty()) {
            sortFields.put("userId", APP.ASC);
        }
        Integer roleId = (Integer) params.get("roleId");
        if (roleId == null) {
            return JsonUtil.getFail(ErrorCodeEnum.INVALID_PARAM, "roleId不能为空");
        }
        Set<Integer> userIdSet = userRoleService.getUserIdSet(roleId);
        IPage<Users> page = getUserPage.apply(ps, userIdSet);
        List<Users> baseUsersList = page.getRecords();
        List<Map<String, Object>> rowList = new ArrayList<>();
        if (baseUsersList.size() > 0) {
            List<Department> departmentList = departmentService.list();
            for (Users user : baseUsersList) {
                Map<String, Object> rowMap = new HashMap<>(8);
                rowMap.put("userId", user.getUserId());
                rowMap.put("loginName", user.getLoginName());
                rowMap.put("userName", user.getUserName());
                rowMap.put("jobCode", user.getJobCode());

                if (departmentList.size() > 0) {
                    String departmentName = departmentList.stream()
                            .filter(department -> department.getDepartmentId().equals(user.getDepartmentId()))
                            .map(Department::getDepartmentName).findFirst().orElse(null);
                    rowMap.put("departmentName", departmentName);
                }
                rowList.add(rowMap);
            }
        }
        return JsonUtil.getSuccess("查询成功").fluentPut(APP.DATA, usersService.getPageResult(page, rowList));
    }

    /**
     * 根据ID查找角色数据
     * @param roleId    角色ID
     * @return          角色数据
     */
    public JSONObject findDataById(Integer roleId) {
        if (roleId == null) {
            return JsonUtil.getFail(ErrorCodeEnum.INVALID_PARAM, "请求参数不能为空");
        }
        Role role = findById(roleId);
        if (role == null) {
            return JsonUtil.getFail(ErrorCodeEnum.DATA_NOT_FOUND, "找不到该角色");
        }
        return JsonUtil.getSuccess("").fluentPut(APP.DATA, JSON.parseObject(JsonUtil.toJsonStringExcludes(role, new String[]{"isDelete"})));
    }

    /**
     * 获取角色表格（分页）
     *
     * @param ps 分页参数
     * @return 表格数据
     */
    public JSONObject loadRolePage(PageParam ps) {
        Map<String, Object> params = ps.getParams();
        int currentPage = ps.getCurrentPage();
        int pageSize = ps.getPageSize();
        Map<String, Object> sortFields = ps.getSort();
        if (sortFields.isEmpty()) {
            sortFields.put("roleId", APP.ASC);
        }
        String[] likeFields = {"roleName", "roleCode"};
        String[] equalFields = {"enable"};
        IPage<Role> page = findPageVue(currentPage, pageSize, params, likeFields, equalFields, sortFields, null);
        List<Role> roleList = page.getRecords();
        JSONObject json = new JSONObject();
        JSONArray dataArray = JSON.parseArray(JsonUtil.toJsonStringExcludes(roleList, new String[]{"isDelete"}));
        json.put(APP.DATA, dataArray);
        json.put(APP.TOTAL_COUNT, page.getTotal());
        json.put(APP.POS, (currentPage - 1) * pageSize);
        json.put(APP.CURRENT_PAGE, page.getCurrent());
        return JsonUtil.getSuccess("查询成功").fluentPut(APP.DATA, json);
    }

    /**
     * 获取角色表格（不分页）
     * @param ps 搜索参数
     * @return
     */
    public JSONObject loadRoleGrid(PageParam ps) {
        Map<String, Object> params = ps.getParams();
        Map<String, Object> sortFields = ps.getSort();
        if (sortFields.isEmpty()) {
            sortFields.put("roleId", APP.ASC);
        }
        String[] likeFields = {"roleName", "roleCode"};
        String[] equalFields = {"enable"};
        QueryWrapper<Role> queryWrapper = getFormSearchWrapperLikeAnd(params, likeFields, equalFields, sortFields, null);
        List<Role> roleList = list(queryWrapper);
        JSONArray dataArray = JSON.parseArray(JsonUtil.toJsonStringExcludes(roleList, new String[]{"isDelete"}));
        return JsonUtil.getSuccess("查询成功").fluentPut(APP.DATA, dataArray);
    }

    /**
     * 删除角色
     *
     * @param roleId 角色ID
     * @return
     */
    public JSONObject deleteRole(Integer roleId) {
        if (roleId == null) {
            return JsonUtil.getFail(ErrorCodeEnum.INVALID_PARAM, "参数不能为空");
        }
        Role role = findById(roleId);
        if (role == null) {
            return JsonUtil.getSuccess("找不到该角色");
        }
        if (RoleIsSystemEnum.SYSTEM_ROLE.equalsValue(role.getIsSystem())) {
            return JsonUtil.getFail(ErrorCodeEnum.DATA_OPERATION_DENY, "不允许删除系统角色");
        }

        List<UserRole> userRoleList = userRoleService.findByProperty(UserRole::getRoleId, role.getRoleId());
        if (userRoleList.size() > 0) {
            userRoleService.deleteBatchByIds(userRoleList.stream().map(UserRole::getId).collect(Collectors.toList()));
        }

        List<RoleRight> roleRightList = roleRightService.findByProperty(RoleRight::getRoleId, role.getRoleId());
        if (roleRightList.size() > 0) {
            roleRightService.deleteBatchByIds(roleRightList.stream().map(RoleRight::getId).collect(Collectors.toList()));
        }
        boolean success = removeById(role.getRoleId());
        if (success) {
            return JsonUtil.getSuccess("删除成功");
        } else {
            return JsonUtil.getFail(ErrorCodeEnum.DATA_OPERATION_FAIL, "删除失败");
        }
    }

    /**
     * 启用/停用角色
     *
     * @param roleId 角色ID
     * @param enable 0：禁用；1：启用；
     * @return
     */
    public JSONObject enableRole(Integer roleId, Integer enable) {
        if (roleId == null || enable == null) {
            return JsonUtil.getFail(ErrorCodeEnum.INVALID_PARAM, "参数不能为空");
        }
        Role role = findById(roleId);
        if (role == null) {
            return JsonUtil.getFail(ErrorCodeEnum.DATA_NOT_FOUND, "找不到该角色");
        }
        LambdaUpdateWrapper<Role> updateWrapper = Wrappers.lambdaUpdate();
        updateWrapper.eq(Role::getRoleId, roleId).set(Role::getEnable, enable);
        boolean success = update(updateWrapper);
        if (success) {
            return JsonUtil.getSuccess("操作成功");
        }
        return JsonUtil.getFail(ErrorCodeEnum.DATA_OPERATION_FAIL, "操作失败");
    }

    /**
     * 查找下拉框可选项数据
     * @param user          当前登录用户信息
     * @param ignoreIds     忽略的ID列表
     * @return  下拉框可选项数据
     */
    public JSONObject loadRoleComboOption(Users user, List<Integer> ignoreIds) {
        LambdaQueryWrapper<Role> queryWrapper = new LambdaQueryWrapper<>();
        // 忽略对应ID的角色
        queryWrapper.notIn(ignoreIds != null && !ignoreIds.isEmpty(), Role::getRoleId, ignoreIds);
        queryWrapper.orderByAsc(Role::getOrderId);
        List<Role> list = list(queryWrapper);

        JSONArray options = new JSONArray();
        if (list != null && list.size() > 0) {
            for (Role role : list) {
                Map<String, Object> mobj = new HashMap<>(4);
                mobj.put("value", role.getRoleId());
                mobj.put("label", role.getRoleName());
                options.add(mobj);
            }
        }

        return JsonUtil.getSuccess("").fluentPut("data", options);
    }

    /**
     * 获取用户的角色列表
     * @param userId 用户ID
     * @param filterDisable true 表示过滤掉停用的角色
     * @return
     */
    public List<Role> getRoleList(Integer userId, boolean filterDisable) {
        Set<Integer> roleIdSet = userRoleService.getRoleIdSet(userId);
        if (roleIdSet.isEmpty()) {
            return new ArrayList<>();
        }
        LambdaQueryWrapper<Role> queryWrapper = Wrappers.lambdaQuery();
        queryWrapper.in(Role::getRoleId, roleIdSet);
        if (filterDisable) {
            queryWrapper.eq(Role::getEnable, RoleEnableEnum.ENABLE.getValue());
        }
        return list(queryWrapper);
    }

    /**
     * 获取启用的角色列表
     * @param userId 用户ID
     * @return 角色列表
     */
    public List<Role> getEnableRoleList(Integer userId) {
        return getRoleList(userId, true);
    }

    /**
     * 获取用户的角色编码列表
     * @param userId 用户ID
     * @return 角色编码列表
     */
    public Set<String> getRoleCodeSet(Integer userId) {
        List<Role> roleList = getEnableRoleList(userId);
        return roleList.stream()
                .filter(role -> StringUtils.isNotBlank(role.getRoleCode()))
                .map(Role::getRoleCode).collect(Collectors.toSet());
    }

    /**
     * 是否系统管理员角色
     * @param roleId 角色ID
     * @return true 表示是系统管理员角色
     */
    public boolean isAdminRole(Integer roleId) {
        return Role.SYSTEM_ROLE_ID_ADMIN.equals(roleId);
    }

    /**
     * 是否包含系统管理员角色
     * @param userId 用户ID
     * @return true 表示该用户包含系统管理员角色
     */
    public boolean isAdminRoleByUserId(Integer userId) {
        // 如果是系统管理员角色，忽略停用属性
        List<Role> roleList = getRoleList(userId, false);
        return roleList.stream().anyMatch(role -> isAdminRole(role.getRoleId()));
    }
}
